#ifndef BASE_FACTORY_HPP
#define BASE_FACTORY_HPP

#include <base/defines.h>
#include <unordered_map>
#include <mutex>
#include <string>

template<typename T>
class Factory {
    public:
        NONCOPYABLE(Factory);
        IMMOVEABLE(Factory);

        static Factory& GetInstance() 
        {
            return instance_;
        }

        T* Register(const std::string& name)
        {
            std::unique_lock<std::mutex> ulk(mtx_);
            auto it = associations_.find(name);
            if (it == associations_.end()) {
                T* tobj = new T();
                T::makeReflectable(name); //每个对象设置不同名字的反射id，不用考虑并发访问和注册             
                associations_.insert({name, tobj});
                return tobj;
            }
            return it -> second;
        }

        bool Unregister(const std::string& name)
        {
            std::unique_lock<std::mutex> ulk(mtx_);
            if (associations_.find(name) != associations_.end()) {
                associations_.erase(name);
                return true;
            }
            return false;
        }

        T* GetObjectPtr(const std::string& name) 
        {
            std::unique_lock<std::mutex> ulk(mtx_);
            auto it = associations_.find(name);
            if (it != associations_.end()) {
                return it -> second;
            }
            return nullptr;
        }
    private:
        Factory() = default;
        ~Factory() 
        {
            for (auto &i : associations_) {
                delete (i.second);
            }
        }
    private:
        static Factory instance_;
        std::unordered_map<std::string, T*> associations_;
        std::mutex mtx_;
};

template <typename T>
Factory<T> Factory<T>::instance_;

#endif